perf(mpsc): replace the unbounded queue backend - #232
Open
tisonkun wants to merge 2 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Part of #209.
Design Notes
The queue stores 31 messages per block. Producers reserve globally ordered slots through one tail CAS, while the unique consumer owns its position without a competing head CAS. The producer reserving the final slot installs the next block before publishing that slot; after reading the final slot, the consumer knows every producer touching the old block has finished and can reclaim it immediately. This follows the segmented-list layout used by crossbeam-channel, specialized for a single consumer and stripped of blocking, selection, and multi-consumer state.
Receiver close sets a bit in the same atomic tail position used for reservation. A sender either reserves before that operation and completes normally, or observes the bit and gets its value back. Cleanup waits only for already-reserved slots, drains them in FIFO order, and then reclaims the final block. Slot publication and the parked-receiver gate participate in one sequentially consistent order: after
register -> arm -> recheck, the receiver either observes the completed slot or its producer observes the arm and performs the wake. Active-receiver sends only read the false gate, avoiding a sharedAtomicWakerwrite on every message.Unsafe code is confined to the queue module. Its invariants are that each successful tail reservation exclusively owns one slot, only the unique consumer reads slots, acquiring
readytransfers the value, and FIFO traversal delays block reclamation until all producers using that block have published. The public receiver remainsSend + Sync + Unpin;Syncis justified at the owned consumer core because shared references cannot advance or close it.The benchmark shapes come from Tokio's MPSC benchmark, Crossbeam's channel benchmark, and Flume's basic benchmark.
crossbeam-channelis benchmark-only. On a local Apple Silicon machine, usingcargo bench -p benchmarks --bench ecosystem -- 'mpsc::unbounded' --min-time 1 --max-time 2, median results changed as follows:mainThe same final run compared the implementations directly in Mitem/s:
Validated with
cargo x check,cargo x test,cargo x lint, and Miri over all focused queue tests.